package com.akka.demo.actor;

import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Terminated;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import com.akka.demo.di.SpringExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by Administrator on 2018/2/26.
 * 设备组管理
 */
@Component
@Scope("prototype")
public class DeviceManager extends AbstractActor {

    static public class RequestTrackDevice {

        private String groupId;
        private String deviceId;

        public RequestTrackDevice(String groupId, String deviceId) {
            this.groupId = groupId;
            this.deviceId = deviceId;
        }

        public String getGroupId() {
            return groupId;
        }

        public void setGroupId(String groupId) {
            this.groupId = groupId;
        }

        public String getDeviceId() {
            return deviceId;
        }

        public void setDeviceId(String deviceId) {
            this.deviceId = deviceId;
        }

    }

    static public class DeviceRegistered {

    }

    private LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);

    private Map<String, ActorRef> groupIdToActor = new HashMap<>();

    private Map<ActorRef, String> actorToGroupId = new HashMap<>();

    @Autowired
    private SpringExtension springExtension;

    @Override
    public void preStart() {
        log.info("DeviceManager started");
    }

    @Override
    public void postStop() {
        log.info("DeviceManager stopped");
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(RequestTrackDevice.class, trackMsg -> {
                    String groupId = trackMsg.getGroupId();
                    if (StringUtils.isEmpty(groupId)) {
                        log.error("no groupId in trackMsg!");
                    } else {
                        if (groupIdToActor.containsKey(groupId)) {
                            ActorRef groupActor = groupIdToActor.get(groupId);
                            groupActor.forward(trackMsg, context());
                        } else {
                            log.info("Creating device group actor for {}", groupId);
                            ActorRef groupActor = context().actorOf(springExtension.props("deviceGroup", groupId), "group-" + groupId);
                            context().watch(groupActor);    //死亡观察功能
                            groupActor.forward(trackMsg, context());
                            groupIdToActor.put(groupId, groupActor);
                            actorToGroupId.put(groupActor, groupId);
                        }
                    }

                })
                .match(DeviceRegistered.class, deviceRegistered -> {
                    log.info("Device registered!!! --- from DeviceManager");
                })
                .match(Terminated.class, terminated -> {    ////当被观察的actor停止时，观察者会接收到Terminated消息
                    ActorRef actorRef = terminated.actor();
                    if (actorToGroupId.containsKey(actorRef)) {
                        String groupId = actorToGroupId.get(actorRef);
                        log.info("DeviceGroup actor for {} has been terminated", groupId);
                        actorToGroupId.remove(actorRef);
                        groupIdToActor.remove(groupId);
                    }
                })
                .build();
    }
}
